<h2>Hex support</h2>

<p>Hexagonal cell layout is supported in several parts of the toolkit, most notably in <a href="#display">Console display</a>, <a href="#map/cellular">Cellular generator</a>, <a href="#fov">FOV</a> and <a href="#path">Pathfinding</a>. This page explains how to uses hexes with rot.js.</p>

<p>While hexagonal cells provide several advantages over the traditional square/rectangular topologies, there is one big complication associated with their usage: there is no canonical way to index individual hexes. A <a href="#hex/indexing">hexagonal indexing comparison</a> document is available for reference; rot.js is using the third variant, called <em>double width</em>.

<h3>Displaying hexes</h3>

<p>There is a very trivial trick to display a rudimentary hexagonal layout: skip even/odd cells in odd/even rows. No special adjustments are necessary. The result will look good as long as the font aspect ratio is close to <code>1:&radic;3</code> &ndash; which is the case for most monospaced fonts.</p>

<div class="example">
var display = new ROT.Display({width:8, height:5});
SHOW(display.getContainer());

for (var y = 0; y &lt; 5; y++) {
	for (var x = y%2; x &lt; 8; x += 2) {
		display.draw(x, y, "&bull;");
	}
}
</div>

<p>For more advanced hexagonal stuff, switch the display to "hex" layout. This has the following advantages:</p>
<ul>
	<li>Precisely computed positioning</li>
	<li>Filled background hexes</li>
</ul>

<div class="example">
var display = new ROT.Display({width:8, height:5, layout:"hex"});
SHOW(display.getContainer());

for (var y = 0; y &lt; 5; y++) {
	for (var x = y%2; x &lt; 8; x += 2) {
		var bg = ROT.RNG.getItem(["#333", "#666", "#999", "#ccc", "#fff"]);
		display.draw(x, y, "&bull;", "#000", bg);
	}
}
</div>

<p>If you <strong>absolutely</strong> need inverted hex layout ("flat-tops"), you can force transposed rendering by passing the <code>transpose:true</code> option to the <code>ROT.Display</code> constructor. Please note that this inverts the x-y values of all display-related functions and operations.</p>

<div class="example">
var display = new ROT.Display({
	width:10, height:4, spacing:2.5,
	layout:"hex", transpose:true
});
SHOW(display.getContainer());

for (var y = 0; y &lt; 4; y++) {
	for (var x = y%2; x &lt; 10; x += 2) {
		var bg = ROT.RNG.getItem(["#333", "#666", "#999", "#ccc", "#fff"]);
		display.draw(x, y, x+","+y, "#000", bg);
	}
}
</div>

<h2>Cellular dungeon generator</h2>

<p>Pass the <code>topology:6</code> option to the <code>ROT.Map.Cellular</code> constructor to operate in hexagonal mode.</p>

<div class="example">
var w = 100, h = 50;
var display = new ROT.Display({width:w, height:h, fontSize:10, layout:"hex"});
SHOW(display.getContainer());

/* hexagonal map and rules */
var map = new ROT.Map.Cellular(w, h, {
	topology: 6,
	born: [4, 5, 6],
	survive: [3, 4, 5, 6]
});

/* initialize with irregularly random values */
for (var i=0; i&lt;w; i++) {
	for (var j=0; j&lt;h; j++) {
		var dx = i/w - 0.5;
		var dy = j/h - 0.5;
		var dist = Math.pow(dx*dx+dy*dy, 0.3);
		if (ROT.RNG.getUniform() &lt; dist) { map.set(i, j, 1); }
	}
}

/* generate four iterations, show the last one */
for (var i=4; i&gt;=0; i--) {
	map.create(i ? null : display.DEBUG);
}
</div>

<h2>Pathfinding</h2>

<p>All pathfinding algorithms accept the <code>topology:6</code> option as well.</p>

<div class="example">
var w = 150, h = 80;
ROT.RNG.setSeed(12345);
var display = new ROT.Display({width:w, height:h, fontSize:6, layout:"hex"});
SHOW(display.getContainer());

/* generate map and store its data */
var data = {};
var map = new ROT.Map.Cellular(w, h, {
	topology: 6,
	born: [4, 5, 6],
	survive: [3, 4, 5, 6]
});
map.randomize(0.48);
map.create(); /* two iterations */
map.create(function(x, y, value) {
	data[x+","+y] = value;
	display.DEBUG(x, y, value);
});

/* input callback informs about map structure */
var passableCallback = function(x, y) {
	return (data[x+","+y] === 0);
}

/* prepare path to given coords */
var dijkstra = new ROT.Path.Dijkstra(120, 64, passableCallback, {topology:6});

/* compute from given coords */
dijkstra.compute(30, 16, function(x, y) {
	display.draw(x, y, "", "", "#800");
});

/* highlight */
display.draw(30, 16, "", "", "#3f3");
display.draw(120, 64, "", "", "#f33");
</div>


<h3>Field of View</h3>

<p>Precise Shadowcasting works in hexagonal topology as well.</p>

<div class="example">
ROT.RNG.setSeed(12345);
var W = 44;
var H = 28;

var display = new ROT.Display({fontSize:12, layout:"hex", width:W, height:H});
SHOW(display.getContainer());

/* generate map and store its data */
var data = {};
var map = new ROT.Map.Cellular(W, H, {
	topology: 6,
	born: [4, 5, 6],
	survive: [3, 4, 5, 6]
});
map.randomize(0.4);
map.create(function(x, y, value) {
	data[x+","+y] = value;
	display.DEBUG(x, y, value);
});

/* input callback */
function lightPasses(x, y) {
	var key = x+","+y;
	if (key in data) { return (data[key] == 0); }
	return false;
}

var fov = new ROT.FOV.PreciseShadowcasting(lightPasses, {topology:6});

/* output callback */
fov.compute(20, 14, 6, function(x, y, r, vis) {
	var ch = (r ? "" : "@");
	var color = (data[x+","+y] ? "#aa0": "#660");
	display.draw(x, y, ch, "#fff", color);
});
</div>
